<?php
/**
 * Game_ResourceWithProduction
 *
 * Класс Game_ResourceWithProduction отвечает за обработку ресурсов
 *
 * @author Дмитрий Кузьма <kouzma.d@gmail.com>
 * @version 1.0
 */
class Game_ResourceWithProduction extends Game_Resource {
	protected static $_resourcesConsumptionAmount = 1;
	private $_arrProductionData = array(); // Массив с информацией о производстве
	private $_arrProductionFinalData = array(); // Массив с информацией о ресурсах
	private $_arrConsumptionStaticData = array(); // Массив с информацией о потреблении (статические объекты - здания)
	private $_arrConsumptionDynamicData = array(); // Массив с информацией о потреблении (динамичсекие объекты - юниты)
	private $_arrCapacityData = array(); // Массив с информацией о вместимости
	private $_arrStartResourcesData = array(); // Массив с начальным количеством ресурсов
	private static $_arrBuildingProduction = array(3, 13, 21, 31, 46, 70, 98, 140, 203, 280, 392, 525, 693, 889, 1120, 1400, 1820, 2240, 2800, 3430, 4270); // Массив производстав "шахт", начиная с 0 уровня
	private $_lastCalc = null;
	
	/**
	 * Конструктор получает данные по производству и по ресурсам
	 * 
	 * @param array $arrResourcesWithProductions
	 */
	public function __construct($arrResourcesWithProductions = array()) {
		// Заполняем данные о ресурсах
		parent::__construct($arrResourcesWithProductions);
		
		// Заполняем данные производства
		for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
			$this->_arrProductionData[$i] = $arrResourcesWithProductions['production_' . $i];
		}
		
		// Заполняем данные потребления
		for ($i = 1; $i <= self::$_resourcesConsumptionAmount; $i++) {
			$this->_arrConsumptionStaticData[$i] = $arrResourcesWithProductions['consumption_static_' . $i];
			$this->_arrConsumptionDynamicData[$i] = $arrResourcesWithProductions['consumption_dynamic_' . $i];
		}
		
		// Заполняем данные финального производства, вычитая из него потребление
		for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
			$this->_arrProductionFinalData[$i] = 
				$this->_arrProductionData[$i]
				- (isset($this->_arrConsumptionStaticData[$i]) ? $this->_arrConsumptionStaticData[$i] : 0)
				- (isset($this->_arrConsumptionDynamicData[$i]) ? $this->_arrConsumptionDynamicData[$i] : 0)
			;
		}
		
		// Заполняем данные вместимости
		for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
			$this->_arrCapacityData[$i] = $arrResourcesWithProductions['capacity_' . $i];
		}
		
		// Заполняем данные о начальном кол-ве ресурсов
		for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
			$this->_arrStartResourcesData[$i] = $arrResourcesWithProductions['resource_' . $i];
		}
		
		// Обновляем значения текущего количества ресурсов
		$this->_lastCalc = $arrResourcesWithProductions['last_calc'];
		$this->_calculateCurrentResourcesData();
  }

  
  /**
   * Метод калькулирует текуущее количество ресурсов у пользователя
   * 
   * @param string $lastCalc - момент относительно которого в последний раз обновлялись данные о ресурсах
   */
	protected function _calculateCurrentResourcesData() {
		$timeDiff = Service_Date::timePassed($this->_lastCalc);
		$secondsAtHour = Service_Date::$timestampOneHourInterval;
		for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
			$this->_arrResourcesData[$i] = min(
				$this->_arrCapacityData[$i],
				intval($this->_arrResourcesData[$i] + $this->_arrProductionFinalData[$i] * $timeDiff / $secondsAtHour)
			);
		}
	} 
	
	/**
	 * Классический геттер
	 * 
	 */
	public function getProductionData() {
		return $this->_arrProductionData;
	}
	/**
	 * Классический геттер
	 * 
	 */
	public function getProductionFinalData() {
		return $this->_arrProductionFinalData;
	}

	/**
	 * Классический геттер
	 *
	 */
	public function getConsumptionStaticData() {
		return $this->_arrConsumptionStaticData;
	}
	

	/**
	 * Классический геттер
	 *
	 */
	public function getConsumptionDynamicData() {
		return $this->_arrConsumptionDynamicData;
	}
	
	/**
	 * Классический геттер
	 *
	 */
	public function getCapacityData() {
		return $this->_arrCapacityData;
	}

	/**
	 * Получает производство определенного уровня здания
	 * 
	 * @param int $level - уровень здания, по которому получаем производство
	 * @return int 
	 */
	public static function getProductionOfLevel($level) {
		return self::$_arrBuildingProduction[$level];
	}
	
	/**
	 * Определяет текущее производство в месте
	 * 
	 * @param array $arrBuildings - массив строений для определения производства
	 * 
	 */
	public function calculateProduction(array &$arrBuildings) {
		$arrResources = array();
		foreach ($arrBuildings as $arrBuilding) {
			if (strpos($arrBuilding['building_name'], 'resource_') === 0) {
				$resourceTypeId = intval(substr($arrBuilding['building_name'], 9));
				if (!isset($arrResources[$resourceTypeId])) $arrResources[$resourceTypeId] = 0;
				$arrResources[$resourceTypeId] += self::$_arrBuildingProduction[$arrBuilding['level']];
			}
		}
		foreach ($arrResources as $resourceId => $productionValue) {
			$this->_arrProductionData[$resourceId] = $productionValue;
		}
	}
	



	/**
	 * Определяет текущее производство в месте
	 *
	 * @param array $arrBuildings - массив строений для определения потребления
	 *
	 */
	public function calculateCapacity(array &$arrBuildings) {
		$arrSumConsumption = array( 1 => 0);
		$capacityOfConsumption = 0;
		$capacityOfNonConsumption = 0;
		
		foreach ($arrBuildings as $arrBuilding) {
			switch ($arrBuilding['ID_building']) {
				case 6:
					$capacityOfConsumption += Game_Building_Storage::getBuildingCapacity($arrBuilding['level']);
					break;
				case 7:
					$capacityOfNonConsumption += Game_Building_Storage::getBuildingCapacity($arrBuilding['level']);
					break;
				default: break;
			}
		}
		$capacityOfConsumption  = max($capacityOfConsumption, 800);
		$capacityOfNonConsumption  = max($capacityOfNonConsumption, 800);
		$arrCapacityByResources = array();
		for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
			$arrCapacityByResources[$i] = ($i <= self::$_resourcesConsumptionAmount) ? $capacityOfConsumption : $capacityOfNonConsumption;
		}
		foreach ($arrCapacityByResources as $resourceId => $capacity) {
			$this->_arrCapacityData[$resourceId] = $capacity;
		}
	}
	
	/**
	 * Определяет текущее потребление списка зданий
	 *
	 * @param array $arrBuildings - массив строений для определения потребления
	 *
	 */
	public function calculateConsumptionStaticData(array &$arrBuildings) {
		$arrSumConsumption = array( 1 => 0);
		foreach ($arrBuildings as $arrBuilding) {
			$arrCurrentConsumption = $this->getBuildingConsumption($arrBuilding, $arrBuilding['level']);
			for ($i = 1; $i <= self::$_resourcesConsumptionAmount; $i++) {
				$arrSumConsumption[$i] += $arrCurrentConsumption[$i];
			}
		}
		foreach ($arrSumConsumption as $resourceId => $consumption) {
			$this->_arrConsumptionStaticData[$resourceId] = $consumption;
		}
	}
	
	/**
	 * Определяет текущее потребление юнитов
	 *
	 * @param array $arrUnits - массив бнитов для определения потребления
	 *
	 */
	public function calculateConsumptionDynamicData(array &$arrUnits) {
		$arrUnitsInfo = Game_Unit::getAllUnitsInfo();
		$arrSumConsumption = array( 1 => 0);
		foreach ($arrUnits as $arrUnitInPlaceData) {
			$unitId = $arrUnitInPlaceData['ID_unit'];
			for ($i = 1; $i <= self::$_resourcesConsumptionAmount; $i++) {
				$arrSumConsumption[$i] += $arrUnitsInfo[$unitId]['consumption_1'] * $arrUnitInPlaceData['amount'];
			}
		}
		// Заполняем данные объекта
		foreach ($arrSumConsumption as $resourceId => $consumption) {
			$this->_arrConsumptionDynamicData[$resourceId] = $consumption;
		}
	}
	
	/**
	 * Получает информацию о потреблении конкретного здания
	 * 
	 * @param array $arrBuilding
	 * @param int $level
	 * @param array $additionalConsumption
	 */
	public static function getBuildingConsumption(array &$arrBuilding, $level) {
		if (!$level) return array (1 => 0); 
		if ($level == 1) {
			return array (1 => $arrBuilding['consumption']);
		}
		else {
			$arrLowerConsumption = self::getBuildingConsumption($arrBuilding, $level - 1);
			$currentConsumption = round ((5 * $arrBuilding['consumption'] + $level - 1) / 10);
			return array (1 => $arrLowerConsumption[1] + $currentConsumption);
		} 
	}
	
	/**
	 * Получает разницу в потреблении различных уровней здания
	 * 
	 * @param array $arrBuilding
	 * @param int $level
	 * @param int $nextLevel
	 * @return array:
	 */
	public static function getBuildingLevelsConsumptionDifference(array &$arrBuilding, $level, $nextLevel) {
		$arrConsumptionDifference = array();
		$nextLevelConsumption = self::getBuildingConsumption($arrBuilding, $nextLevel);
		$previosLevelConsumption = self::getBuildingConsumption($arrBuilding, $level);
		for ($i = 1; $i <= self::$_resourcesConsumptionAmount; $i++) {
			$arrConsumptionDifference[$i] = $nextLevelConsumption[$i] - $previosLevelConsumption[$i];
		}
		return $arrConsumptionDifference;
	}
  /**
   * Метод получает двумерный массив данных для сохранения в БД
   * 
   */
  public function getDataForDatabase() {
  	$arrRet = parent::getDataForDatabase();
  	for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
			 $arrRet['production_' . $i] = $this->_arrProductionData[$i];
			 $arrRet['capacity_' . $i] = $this->_arrCapacityData[$i];
			 if (isset($this->_arrConsumptionStaticData[$i])) $arrRet['consumption_static_' . $i] = $this->_arrConsumptionStaticData[$i];
			 if (isset($this->_arrConsumptionDynamicData[$i])) $arrRet['consumption_dynamic_' . $i] = $this->_arrConsumptionDynamicData[$i];
		}
		return $arrRet;
  }
  
  /**
   * Подсчитывает, через какое кол-во секунд будет достаточно ресурсов
   *
   * @param Game_Resource $objResourceToPay
   */
  public function calculateSecondsToEnoughResources(Game_Resource $objResourceToPay) {
  	$arrResourceToPay = $objResourceToPay->getResourcesData();
  	$maxSecondsFromStart = 0;
  	$mainResoure = null; // Ресурс, которого не хватает
  	for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
  		if ($this->_arrStartResourcesData[$i] < $arrResourceToPay[$i]) {
  			if ($arrResourceToPay[$i] > $this->_arrCapacityData[$i]) return -1;
  			$delta = $arrResourceToPay[$i] - $this->_arrStartResourcesData[$i];
  			$seconds = $delta * 60 * 60 / $this->_arrProductionData[$i];
  			if ($seconds > $maxSecondsFromStart) {
  				$mainResoure = $i;
  				$maxSecondsFromStart = $seconds;
  			}
  		}
  	}

  	return $maxSecondsFromStart - Service_Date::timePassed($this->_lastCalc);
  }
  
  public function increase(Game_Resource $objResource) {
  	parent::increase($objResource);
  	for ($i = 1; $i <= self::$_resourcesAmount; $i++) {
  		$this->_arrResourcesData[$i] = min(
  				$this->_arrCapacityData[$i],
  				$this->_arrResourcesData[$i]
  		);
  	}
  }
}
?>